﻿using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using KinonekoSoftware.ArkSpark.Core;
using KinonekoSoftware.ArkSpark.Runtimes;
using KinonekoSoftware.Foundation.UI.Controls;
using KinonekoSoftware.Foundation.UI.Controls.Selectors;

namespace KinonekoSoftware.ArkSpark.Controls
{
    public sealed class DocumentEditorItem : ForestListBoxItem
    {
        private                WeakReference<DocumentEditor> _asTextEditorReference;
        public static readonly StyledProperty<bool>          IsSelectableProperty = AvaloniaProperty.Register<DocumentEditorItem, bool>(nameof(IsSelectable));


        static DocumentEditorItem()
        {
            IsSelectedProperty.Changed.Subscribe(x =>
            {
                var sender = x.Sender as DocumentEditorItem;


                if (x.GetNewValue<bool>())
                {
                    sender?.OnSelected();
                }
                else
                {
                    sender?.OnUnselected();
                }
            });
        }
        
        public DocumentEditorItem()
        {
            DataContextChanged += OnDataContextChanged;
        }
        
        private void OnDataContextChanged(object sender, EventArgs e)
        {
            IsSelectable = DataContext is IArkSparkModel { IsSelectable: true };
        }


        private void SendMessage(IArkSparkModel iArkSparkModel, DocumentEditor editor)
        {
            //
            // 设置选择的元素
            editor.MessageBus?.OnNext(new NewSelectionEventArgs
            {
                EditingItem = iArkSparkModel,
            });

            //
            // 设置编辑状态。
            if (iArkSparkModel is IArkSparkRuntimeModel iArkSparkRTM)
            {
                iArkSparkRTM.IsEdit = IsSelected;
            }
        }


        private void OnSelected()
        {
            var editor = TextEditor;

            if (DataContext is not IArkSparkModel iArkSparkModel)
            {
                return;
            }

            if (editor is null)
            {
                return;
            }

            if (!iArkSparkModel.IsSelectable)
            {
                return;
            }


            if (iArkSparkModel.UseWYSIWYGEditor)
            {
                SetCorrectionTemplate(iArkSparkModel);
                SendMessage(iArkSparkModel, editor);
            }
            else
            {
                editor.MessageBus
                      .OnNext(new NewSelectionEventArgs
                       {
                           EditingItem     = (DocumentElementPresenter)iArkSparkModel,
                           WYSIWYGEditMode = true,
                       });
            }
        }

        private void OnUnselected()
        {
            if (DataContext is not IArkSparkModel iArkSparkModel)
            {
                return;
            }


            if (iArkSparkModel.IsSelectable)
            {
                SetCorrectionTemplate(iArkSparkModel);
            }


        }

        private void SetCorrectionTemplate(IArkSparkModel iArkSparkModel)
        {
            var editor    = TextEditor;
            var resources = IsSelected ? editor.EditingResources : editor.Resources;
            var type      = iArkSparkModel.GetType();

            if (resources is null)
            {
                return;
            }

            // ContentTemplate = resources[new DataTemplateKey(type)] as DataTemplate;
        }


        internal DocumentEditor TextEditor
        {
            get
            {
                DocumentEditor editor;

                if (_asTextEditorReference is null)
                {
                    editor                 = Xaml.GetParent<DocumentEditor>(this);
                    _asTextEditorReference = new WeakReference<DocumentEditor>(editor);
                }

                if (!_asTextEditorReference.TryGetTarget(out editor))
                {
                    editor = Xaml.GetParent<DocumentEditor>(this);
                    _asTextEditorReference.SetTarget(editor);
                }

                return editor;
            }
        }

        public bool IsSelectable
        {
            get => GetValue(IsSelectableProperty);
            set => SetValue(IsSelectableProperty, value);
        }
    }
}